home *** CD-ROM | disk | FTP | other *** search
- (*****************************************************************************)
- (* *)
- (* TVGRAPH Version 1.0 (C) C.L.Burke. Portions (C) Borland *)
- (* *)
- (* Display Specific routines *)
- (* *)
- (* 0. Do_Set_XXXXXX - sets all of the functions into the procedure array *)
- (* *)
- (* 1. Do_INIT_XXXXXX - should initialise all the specific hardware *)
- (* 2. Do_DONE_XXXXXX - should reset all specific hardware *)
- (* 3. Do_PixelAddr_XXXXXX *)
- (* - in ax=y, bx=x | out AH=unshifted bit mask *)
- (* - CL=bits to shift BX = byte offset *)
- (* 4. TVGraphCursorOn_XXXXXX *)
- (* These 3 routines assume GLOBAL TvGraphCursor *)
- (* has Start in H and end in L. GLOBAL TvGraphLoc *)
- (* X in L and Y in H *)
- (* - Turn Cursor on check TvViziFlag *)
- (* 5. TVGraphCursorOff_XXXXXX *)
- (* - Turn Cursor off check TvViziFlag *)
- (* 6. TVUpdateCursor_XXXXXX *)
- (* - Update cursor to current specifications *)
- (* 7. Do_GraphMOV_XXXXX- expect same parameters at REP MOVSW to text video *)
- (* - CX = Number of words (HI=Attr,LO=Char) to move *)
- (* - DS:SI = Source of words *)
- (* - ES:DI = Normal TEXT destination *)
- (* 8. NewJmp_GraphMOV_XXXXXX *)
- (* - Replaces the CheckSnow code in Views unit *)
- (* - important that the following structure is kept *)
- (* *)
- (* asm *)
- (* call far ptr Do_GraphMOV_XXXXXX *)
- (* mov si,es *)
- (* pop ax *)
- (* pop cx *)
- (* pop di *)
- (* pop ds *)
- (* pop es *)
- (* db 0C3H ( RET NEAR - can't use RET FAR!!! ) *)
- (* end; *)
- (* 9. procedure Draw_Any_Line_XXXXXX(X1,Y1,X2,Y2,Color:word); assembler; *)
- (* Generic draw routine assumes X1<X2 *)
- (* *)
- (* 10. procedure Draw_Horiz_Line_XXXXXX(X1,X2,Y,Color:word); assembler; *)
- (* Horizontal draw routine assumes X1<X2 *)
- (* *)
- (* 11. procedure Draw_Vert_Line_XXXXXX(X,Y1,Y2,Color:word); assembler; *)
- (* Vertical draw routine assumes Y1<Y2 *)
- (* *)
- (*****************************************************************************)
- const (* EGA Specific constants *)
- EGAVideoMemory =$A000;
- EGASequencer =$03C4;
- EGAGraphController =$03CE;
- Set_EnableSR =$0001;
- UseSR =$0F00;
- UseCPUMask =$0000;
- Default_EnableSR =Set_EnableSR+UseSR;
- Set_RWFunction =$0003;
- OverWrite =$0000;
- LogicalAND =$0800;
- LogicalOR =$1000;
- LogicalXOR =$1800;
- Default_RWFunction =Set_RWFunction+OverWrite;
- Set_WriteMode =$0005;
- Read_Mode_0 =$0000;
- Read_Mode_1 =$0800;
- Write_Mode_0 =$0000;
- Write_Mode_1 =$0100;
- Write_Mode_2 =$0200;
- Write_Mode_3 =$0300;
- Default_WriteMode =Set_WriteMode+Read_Mode_1+Write_Mode_0;
- Default_ColorPlane =$0007;
- Default_Mask =$FF08;
-
- BytesInLoop =10; (* Bytes in the simulated loop *)
- NumberOfLoops =16; (* Number of coded loops *)
- var (* GLobal to free BP in draw line routines *)
- VARSlope:byte; (* 0 = slope < 1 , 1= slope >1 *)
- BitShift,ReInitBit,NegBitShift,
- CharMapPtr,VARVertIncr,VARIncr1,VARIncr2:word;
-
-
- Procedure Do_INIT_EGAVGA; assembler;
- asm
- (* Call once at start of program *)
- (* all ega/vga routines should return to this state *)
- push ax
- push cx
- push dx
- push es
- push si
-
- xor ah,ah
- xor ch,ch
- mov ax,[GraphWidth]
- div [CharWidth]
- mul [GraphHeight]
- mov [ColorList],ax
- mov si,ax
- mov ax,[VideoBufferSeg]
- mov es,ax
-
- mov dx,EGAGraphController (* Set up Graphics controller *)
- mov ax,Default_EnableSR
- out dx,ax
- mov ax,Set_WriteMode+Read_Mode_1+Write_Mode_2 (* For Color init next *)
- out dx,ax
- mov ax,Default_RWFunction
- out dx,ax
- mov ax,Default_Mask
- out dx,ax
- mov ax,Default_ColorPlane
- out dx,ax
-
-
- mov al,0ffh
- mov ch,010h
- mov cl,0
- (* ES:SI = SCreen , CX=Count, DX=port *)
- @L10:
- and es:[si],cl
- inc si
- inc cl
- dec ch
- jnz @L10
-
- mov ax,Default_WriteMode
- out dx,ax
-
- (* Set up 16 colors at EGAScreenSegment:[SI] where SI=max-x max-y *)
- pop si
- pop es
- pop dx
- pop cx
- pop ax
- ret
- end;
-
-
- Procedure Do_DONE_EGAVGA; assembler;
- asm
- (* Call once at end of program *)
- push ax
- push dx
- mov dx,EGAGraphController (* Set up Graphics controller *)
- mov ax,Default_Mask (* Restore CRT registers *)
- out dx,ax
- mov ax,Set_WriteMode+Read_Mode_0+Write_Mode_0
- out dx,ax
- mov ax,Set_RWFunction+OverWrite
- out dx,ax
- mov ax,Default_ColorPlane
- mov ah,0Fh
- out dx,ax
- pop dx
- pop ax
- ret
- end;
-
- procedure Do_PixelAddr_EGAVGA; assembler;
- asm
- (* in ax=y, bx=x | *)
- (* CL=bits to shift BX = byte offset *)
- (* BX=Y*80+X/8 = Y*64+Y*16+X/8 = Y SHL 4 + Y SHL 6 + X SHR 3 *)
- (* CL=BL and 7 *)
- mov ch,bl
- and ch,7 (* mask *)
- mov cl,3
- shr bx,cl (* bx=X/8 *)
- inc cl
- shl ax,cl (* ax=Y*16 *)
- add bx,ax (* bx=Y*16+X/8 *)
- shl ax,1
- shl ax,1 (* ax=Y*64 *)
- add bx,ax (* bx=Y*64+Y*16+X/8 *)
- mov cl,ch
- end;
-
- procedure Do_Cursor_EGAVGA; assembler;
- asm
- (* Expect CH = start, CL = stop line (0..16), - in TvGraphCursor*)
- (* Expect X in DL, Y in DH - character co-ords - in TvGraphPos *)
- push cx
- push dx
- push si
- push es
- xor [TvViziFlag],0FFh
- mov cx,[TvGraphCursor]
- mov dx,[TvGraphLoc]
-
- and cx,01F1Fh (* ensure each is 0..31 only *)
- cmp cl,ch
- jb @SKIP
- push cx
- mov al,CharHeight
- mul dh (* ax:= Y*CharHeight *)
-
- xor dh,dh
- mov si,dx (* Si = X *)
-
- xchg ch,cl
- xor ch,ch
- add ax,cx (* ax:= Y*CharHeight+StartLine *)
- mov cx,80
- mul cx (* ax:= (Y*CharHeight+StartLine)*80 *)
- add ax,dx (* ax:= (Y*CharHeight+StartLine)*80 *)
- add si,ax (* si:= (Y*CharHeight+StartLine)*80 + X *)
- pop cx
- mov al,cl
- xor ah,ah
- sub al,ch (* al:= (StopLine - StartLine) *)
- inc al (* al:= (StopLine - StartLine)+1 *)
- mov cx,ax (* use as loop count *)
- mov ax,[VideoBufferSeg] (* VideoBufferSeg *)
- mov es,ax
- cli
- mov dx,EGAGraphController (* Set up Graphics controller *)
- mov ax,Default_EnableSR
- out dx,ax
- mov ax,Default_ColorPlane
- out dx,ax
- mov ax,Set_WriteMode+Read_Mode_1+Write_Mode_2
- out dx,ax
- mov ax,Default_Mask
- out dx,ax
- mov ax,Set_RWFunction+LogicalXOR
- out dx,ax
- mov al,0ffh
-
- (* ES:SI = SCreen , AX=Temp, CX=Count, DX=port *)
- @L10:
- and es:[si],al
- add si,80
- loop @L10
- sti
- @SKIP:
- pop es
- pop si
- pop dx
- pop cx
-
- ret
- end;
-
- procedure TVGraphCursorOn_EGAVGA; assembler;
- asm
- cmp TvViziFlag,0
- jne @OnOK
- jmp Do_Cursor_EGAVGA
- @OnOK:
- ret
- end;
-
- procedure TVGraphCursorOff_EGAVGA; assembler;
- asm
- cmp TvViziFlag,0
- je @OffOK
- jmp Do_Cursor_EGAVGA
- @OffOK:
- ret
- end;
-
- procedure TVUpdateCursor_EGAVGA; assembler;
- asm
- test TvGraphCursor,$E000
- jz @DOIRET_ON
- jmp TvGraphCursorOff_EGAVGA
- @DOIRET_ON:
- jmp TvGraphCursorOn_EGAVGA
- end;
-
- procedure Do_GraphMOV_EGAVGA; assembler;
- asm
- (* Expect CX = Number of words (HI=Attr,LO=Char) to move *)
- (* Expect DS:SI = Source of words *)
- (* Expect ES:DI = Normal TEXT destination *)
-
- push es
- push bp
- push dx
- push bx (* Save register that may be changes by a TP procedure *)
- push bp
-
- mov dx,ds
- mov ax,seg @data (* Set up data segment *)
- mov ds,ax
- mov es,ax
- mov [TextSource.S],dx
- mov [TextSource.O],si
- mov [Count],cx
-
- call MouseCursorOff
- call TvGraphCursorOff_EGAVGA
-
- mov ax,di
- xor dx,dx
- mov cx,0A0h
- div cx (* dx= O mod 160 , ax= O div 160 *)
- shr dx,1
- mov bx,dx (* X=bx , Y=ax *)
-
- mul [CharHeight] (* ax := Y(text)*Rowsperline *)
-
- mov dx,80 (*BytesPerLine*)
- mul dx
- add bx,ax (* End Routine PixelAddr10 *)
- (* BX -> offset to Buffer *)
- mov [DestOfs],bx
-
- shr di,1 (* Convert index to one with no attributes *)
- add di,offset GraphWriteAvail
- mov [TextDest],di
-
- mov al,NumberOfLoops
- mov bl,BytesInLoop
- sub al,[CharHeight] (* Number of loop segments to skip *)
- and al,0Fh (* ensure in range 0..15 *)
- mul bl (* Number of bytes to skip *)
- add ax,OFFSET @STARTLP (* Location to jump to *)
- mov [SaveJump],ax (* DX has offset to jump to using jmp [dx] *)
-
- @GLP1:
- les si,[TextSource]
- mov ax,es:[si]
-
- mov bl,ah (* BL has Attr *)
- mov bh,ah
- mov cl,4
- and bl,00Fh
- and bh,0F0h
- shr bh,cl (* bh = background, bl = foreground *)
-
- mov di,[TextDest]
- cmp ah,0ffh
- jz @NotText (* ffh is attr signal for graphics *)
- mov byte ptr [di],0
- jmp @IsText
- @NotText:
- mov byte ptr [di],al (* when attr=FF then char is window number *)
- mov bx,0 (* Foreground 0 background 0 *)
- mov ax,20h (* Space character *)
- @IsText:
- xor ah,ah (* AX has character *)
-
- les di,[PtrFontTable] (* shl by 4 = *16 for index into font table *)
- shl ax,cl
- add di,ax (* ES:DI = font table for character *)
-
- xor ch,ch
-
- mov cl,bh (* Background color *)
- mov bp,[ColorList] (* EGAScreenSegment:BP = List of colors in ega memory *)
- add bp,cx (* EGAScreenSegment:BP = actual color pointer in ega *)
-
- mov cl,[CharHeight] (* CL has height = times to do @L10 *)
-
- mov cx,[SaveJump] (* Get the jump location *)
-
- push ds
- mov ax,[VideoBufferSeg] (* VideoBufferSeg *)
- mov si,[DestOfs]
- mov ds,ax (* DS:SI = Screen Address *)
-
- (* ES:DI = Font, DS:SI = SCreen , AX=Temp, BX= attr, CX=Count, DX=port *)
- (* DS:BP = location of color in ega memory *)
-
- cli
- mov dx,EGAGraphController (* Set up Graphics controller *)
- mov ax,Default_EnableSR
- out dx,ax
- mov ax,Default_WriteMode
- out dx,ax
- mov ax,Default_RWFunction
- out dx,ax
- mov ax,Default_ColorPlane
- out dx,ax
-
- mov ah,ds:[bp] (* Latch background color to memory *)
- mov al,00
- mov ah,bl
- out dx,ax (* foreground color to Set/Reset register *)
-
- mov al,8
- mov bl,0FFh
-
- jmp cx (* jump to start should be 0 for 16, 2 for 14 *)
-
- @STARTLP:
- (* 0 *) (* CYCLES / BYTES *)
- mov ah,es:[di] (* 4 / 3 *)
- out dx,ax (* 11 / 1 *)
- mov [si],bl (* 4 / 2 *)
- inc di (* 2 / 1 *)
- add si,80 (*BytesPerLine*) (* 2 / 3 *)
- (* 1 *) (* 23 / 10 TOTAL *)
- mov ah,es:[di]
- out dx,ax
- mov [si],bl
- inc di
- add si,80 (*BytesPerLine*)
- (* 2 *)
- mov ah,es:[di]
- out dx,ax
- mov [si],bl
- inc di
- add si,80 (*BytesPerLine*)
- (* 3 *)
- mov ah,es:[di]
- out dx,ax
- mov [si],bl
- inc di
- add si,80 (*BytesPerLine*)
- (* 4 *)
- mov ah,es:[di]
- out dx,ax
- mov [si],bl
- inc di
- add si,80 (*BytesPerLine*)
- (* 5 *)
- mov ah,es:[di]
- out dx,ax
- mov [si],bl
- inc di
- add si,80 (*BytesPerLine*)
- (* 6 *)
- mov ah,es:[di]
- out dx,ax
- mov [si],bl
- inc di
- add si,80 (*BytesPerLine*)
- (* 7 *)
- mov ah,es:[di]
- out dx,ax
- mov [si],bl
- inc di
- add si,80 (*BytesPerLine*)
- (* 8 *)
- mov ah,es:[di]
- out dx,ax
- mov [si],bl
- inc di
- add si,80 (*BytesPerLine*)
- (* 9 *)
- mov ah,es:[di]
- out dx,ax
- mov [si],bl
- inc di
- add si,80 (*BytesPerLine*)
- (*10 *)
- mov ah,es:[di]
- out dx,ax
- mov [si],bl
- inc di
- add si,80 (*BytesPerLine*)
- (*11 *)
- mov ah,es:[di]
- out dx,ax
- mov [si],bl
- inc di
- add si,80 (*BytesPerLine*)
- (*12 *)
- mov ah,es:[di]
- out dx,ax
- mov [si],bl
- inc di
- add si,80 (*BytesPerLine*)
- (*13 *)
- mov ah,es:[di]
- out dx,ax
- mov [si],bl
- inc di
- add si,80 (*BytesPerLine*)
- (*14 *)
- mov ah,es:[di]
- out dx,ax
- mov [si],bl
- inc di
- add si,80 (*BytesPerLine*)
- (*15 *)
- mov ah,es:[di]
- out dx,ax
- mov [si],bl
- inc di
- add si,80 (*BytesPerLine*)
- sti
-
- pop ds
- inc [TextSource.O]
- inc [TextSource.O]
- inc [TextDest]
- inc [DestOfs]
- dec [Count]
- jnz @GLP1
-
- call MouseCursorOn
- call TvUpdateCursor_EGAVGA
-
- pop bp
- pop bx (* Restore registers *)
- pop dx
- pop bp
- pop es
-
- retf
- end;
-
- procedure NewJmp_GraphMOV_EGAVGA; assembler;
- asm
- call far ptr Do_GraphMOV_EGAVGA (* 5 *)
- mov si,es (* 2 *) (* Normal Return code *)
- pop ax (* 1 *)
- pop cx (* 1 *)
- pop di (* 1 *)
- pop ds (* 1 *)
- pop es (* 1 *)
- db 0C3H (* RET NEAR *) (* 1 *)
- end; (*TOTAL 13 bytes*)
-
-
- procedure Do_TextAddr_EGAVGA; assembler;
- asm
- (* start AX=Y, BX=X
- (* Output SI=CharMapPtr,BX=NegBitShift,DX=BitShift*)
- (* AX=ReInitBit *)
- (* Calculate the start location of bitmap *)
- DIV [CharHeight]
- MOV CL,AH (* Remainder = 0..Charheight-1 *)
- MUL [ScreenWidth]
- SHR BX,1
- SHR BX,1
- SHR BX,1
- ADD AX,BX (* AX is offset into table *)
- ADD AX,Offset GraphWriteAvail
- mov SI,AX
-
-
- mov ax,08000h
- mov bx,ax
- mov dx,ax
-
- (* The following are used for determining when a character boundary has *)
- (* Been breached in graphics mode - bx and dx give the initial amount to*)
- (* rotate left - when carry inc SI i.e. adc si,0, ax give the normal one*)
- (* to initialize to when carry is found *)
-
- shr bx,cl (* Head start for shifting initial -ive*)
- sub cl,[CharHeight]
- neg cl
- dec cl
- shr dx,cl (* Head start for shifting initial +ive *)
- mov cl,[CharHeight]
- dec cl
- shr ax,cl (* Head start for shifting normal +/- ive *)
- end;
-
-
-
- procedure Draw_Vert_Line_EGAVGA(X,Y1,Y2:word;Color:byte); assembler;
- asm
- (* Assumes that Y1<Y2 for vertical lines *)
- cli
-
- mov ax,[Y1]
- mov bx,[X]
- call Do_TextAddr_EGAVGA
- mov [CharMapPtr],si
- mov [BitShift],dx
- mov [ReInitBit],ax
-
- mov dx,EGAGraphController
-
- mov ah,[Color]
- xor al,al
- out dx,ax
-
- mov ax,Set_EnableSR+UseSR
- out dx,ax
-
- mov ax,Default_RWFunction
- mov ah,[CurrentLineWriteMode]
- shl ah,1
- shl ah,1
- shl ah,1
- out dx,ax
-
- mov ax,Default_WriteMode
- out dx,ax
- mov ax,Default_ColorPlane
- out dx,ax
-
-
- mov si,[BytesPerLine]
- mov ax,EGAVideoMemory
- mov es,ax
-
- mov ax,[y1] (* AX := y1 *)
- mov bx,[y2] (* BX := y2 *)
- mov cx,bx
- sub cx,ax (* CX := dy *)
-
- inc cx (* CX := # of pixels to draw *)
- mov bx,[x] (* BX := x *)
- push cx (* preserve this register *)
- call Do_PixelAddr_EGAVGA
- (* BX -> video buffer *)
- (* CL := # bits to shift right *)
- (* set up Graphics Controller *)
- mov ah,080h
- shr ah,cl (* AH := bit mask in proper position *)
- mov al,8 (* AL := Bit Mask reg number *)
- out dx,ax
-
- pop cx (* restore this register *)
-
- (* draw the line *)
- (* USES ES,BX,AL,SI,CX - avail DI,DX,AH,BP *)
- mov ah,[CurrentGraphWindow]
- mov di,[CharMapPtr]
- mov dx,[BitShift] (* get rotated left, if carry then inc *)
- (* bx from CharMapPtr *)
-
- @L32: cmp byte ptr [di],ah
- jne @L32a
- or es:[bx],al (* set pixel *)
- @L32a: add bx,si (* increment to next line *)
- rol dx,1 (* rotate left when 1 inc bx *)
- jnc @L32b
- add di,si
- mov dx,[ReInitBit]
- @L32b: loop @L32
-
- sti
- end;
-
-
-
- procedure Draw_Horiz_Line_EGAVGA(X1,X2,Y:word;Color:byte); assembler;
- asm
- cli
- mov ax,[Y]
- mov bx,[X1]
- call Do_TextAddr_EGAVGA
- mov [CharMapPtr],si
-
- mov dx,EGAGraphController
-
- mov ah,[Color]
- xor al,al
- out dx,ax
-
- mov ax,Set_EnableSR+UseSR
- out dx,ax
-
- mov ax,Default_RWFunction
- mov ah,[CurrentLineWriteMode]
- shl ah,1
- shl ah,1
- shl ah,1
- out dx,ax
-
- mov ax,Default_WriteMode
- out dx,ax
- mov ax,Default_ColorPlane
- out dx,ax
-
- mov si,[BytesPerLine]
- mov ax,EGAVideoMemory
- mov es,ax
-
- mov ax,[Y]
- mov bx,[X1]
- call Do_PixelAddr_EGAVGA
- (* ES:BX -> video buffer *)
- (* CL := # bits to shift left *)
- mov di,bx (* ES:DI -> buffer *)
-
- mov dx,0FFFFh (* DH := unshifted bit mask for leftmost *)
- (* byte *)
- shr dh,cl (* DH := bit mask for first byte *)
-
- mov cx,[x2]
- and cl,7
- xor cl,7 (* CL := number of bits to shift left *)
- shl dl,cl (* DL := bit mask for last byte *)
-
- (* determine byte offset of first and last pixel in the line *)
-
- mov ax,[x2] (* AX := x2 *)
- mov bx,[x1] (* BX := x1 *)
-
- mov cl,3 (* number of bits to shift to *)
- (* convert pixels to bytes *)
-
- shr ax,cl (* AX := byte offset of x2 *)
- shr bx,cl (* BX := byte offset of x1 *)
- mov cx,ax
- sub cx,bx (* CX := (# bytes in line) - 1 *)
-
- (* get Graphics Controller port address into DX *)
-
- mov bx,dx (* BH := bit mask for first byte *)
- (* BL := bit mask for last byte *)
- mov dx,3CEh (* DX := Graphics Controller port *)
- mov al,8 (* AL := Bit Mask Register number *)
- mov si,[CharMapPtr]
-
- (* set pixels in leftmost byte of the line *)
-
- or bh,bh
- js @L43 (* jump if byte-aligned (x1 is leftmost *)
- (* pixel in byte) *)
- or cx,cx
- jnz @L42 (* jump if more than one byte in the line *)
-
- and bl,bh (* BL := bit mask for the line *)
- jmp @L44
-
- @L42: mov ah,bh (* AH := bit mask for 1st byte *)
- mov bh,[CurrentGraphWindow]
- cmp [si],bh
- jnz @L42a
- out dx,ax (* update Graphics Controller *)
- or es:[di],al (* update bit planes *)
- @L42a:
- inc di
- inc si
- dec cx
-
- (* use a fast 8086 machine instruction to draw the remainder of the line *)
-
- @L43: jcxz @L44
- mov ah,11111111b (* AH := bit mask *)
- out dx,ax (* update Bit Mask Register *)
- mov ah,[CurrentGraphWindow]
-
- @L43a: cmp [si],ah
- jnz @L43b
- or es:[di],al (* update bit planes *)
- @L43b: inc si
- inc di
- loop @L43a
-
- (* set pixels in the rightmost byte of the line *)
-
- @L44: mov ah,bl (* AH := bit mask for last byte *)
- mov bl,[CurrentGraphWindow]
- cmp [si],bl
- jnz @L44a
- out dx,ax (* update Graphics Controller *)
- or es:[di],al
- @L44a: sti
-
- end;
-
- (*Version 3 of this draw routine - includes partial overwrite protection *)
- procedure Draw_Any_Line_EGAVGA(X1,Y1,X2,Y2:word;Color:byte); assembler;
- asm
- cli
- push bp
- mov ax,[Y1]
- mov bx,[X1]
- call Do_TextAddr_EGAVGA
- mov [CharMapPtr],si
- mov [BitShift],dx
- mov [NegBitShift],bx
- mov [ReInitBit],ax
-
- mov dx,EGAGraphController
-
- mov ah,[Color]
- xor al,al
- out dx,ax
-
- mov ax,Set_EnableSR+UseSR
- out dx,ax
-
- mov ax,Default_RWFunction
- mov ah,[CurrentLineWriteMode]
- shl ah,1
- shl ah,1
- shl ah,1
- out dx,ax
-
- mov ax,Default_WriteMode
- out dx,ax
- mov ax,Default_ColorPlane
- out dx,ax
-
- mov si,[BytesPerLine]
- mov ax,EGAVideoMemory
- mov es,ax
-
- mov cx,[x2]
- sub cx,[x1]
-
-
- @L01: mov bx,[y2]
- sub bx,[y1] (* BX := y2 - y1 *)
-
- jns @L03 (* jump if slope is positive *)
- push [NegBitShift] (* Start with negative bit shift *)
- pop [BitShift]
- neg bx (* BX := y1 - y2 *)
- neg si (* negate increment for buffer interleave *)
-
- (* select appropriate routine for slope of line *)
-
- @L03: mov [VARvertincr],si (* save vertical increment *)
- mov byte ptr [VARSlope],0
- cmp bx,cx
- jle @L04 (* jump if dy <= dx (slope <= 1) *)
- mov byte ptr [VARslope],1
- xchg bx,cx (* exchange dy and dx *)
-
- (* calculate initial decision variable and increments *)
-
- @L04: shl bx,1 (* BX := 2 * dy *)
- mov [VARincr1],bx (* incr1 := 2 * dy *)
- sub bx,cx
- mov si,bx (* SI := d = 2 * dy - dx *)
- sub bx,cx
- mov [VARincr2],bx (* incr2 := 2 * (dy - dx) *)
-
- (* calculate first pixel address *)
-
- push cx (* preserve this register *)
- mov ax,[y1] (* AX := y *)
- mov bx,[x1] (* BX := x *)
- call Do_PixelAddr_EGAVGA
- (* ES:BX -> buffer *)
- (* CL := # bits to shift left *)
-
- mov di,bx (* ES:DI -> buffer *)
- mov ah,080h
- shr ah,cl (* AH := bit mask in proper position *)
- mov bl,ah (* AH,BL := bit mask *)
- mov al,8 (* AL := Bit Mask Register number *)
- pop cx (* restore this register *)
- inc cx (* CX := # of pixels to draw *)
-
- mov bp,[CharMapPtr]
- mov bh,[CurrentGraphWindow]
-
- cmp byte ptr [VARSlope],1
- jz @HiSlopeLine
-
- (* Use BP for CharMapPtr and BH for CurrentWindowId *)
-
- @L10: mov ah,bl (* AH := bit mask for next pixel *)
-
- @L11: or ah,bl (* mask current pixel position *)
- ror bl,1 (* rotate pixel value *)
- jc @L14 (* jump if bit mask rotated to *)
- (* leftmost pixel position *)
- (* bit mask not shifted out *)
-
- or si,si (* test sign of d *)
- jns @L12 (* jump if d >= 0 *)
-
- add si,[VARincr1] (* d := d + incr1 *)
- loop @L11
-
- cmp ds:[bp],bh
- jnz @L11a
-
- out dx,ax (* update Bit Mask Register *)
- or es:[di],al (* set remaining pixel(s) *)
- @L11a:
- jmp @LineDone
-
- @L12: add si,[VARincr2] (* d := d + incr2 *)
- cmp ds:[bp],bh
- jnz @L12a
-
- out dx,ax (* update Bit Mask Register *)
- or es:[di],al (* update bit planes *)
-
- @L12a: add di,[VARvertincr] (* increment y *)
- rol word ptr [BitShift],1
- jnc @L12b
-
- add bp,[VARVertincr]
- push [ReInitBit]
- pop [BitShift]
-
- @L12b: loop @L10
- jmp @LineDone
-
- (* bit mask shifted out *)
-
- @L14: cmp ds:[bp],bh
- jnz @L14a
-
- out dx,ax (* update Bit Mask Register ... *)
- or es:[di],al (* update bit planes *)
-
- @L14a: inc di (* increment x *)
- inc bp
-
- or si,si (* test sign of d *)
- jns @L15 (* jump if non-negative *)
-
- add si,[VARincr1] (* d := d + incr1 *)
- loop @L10
- jmp @LineDone
-
- @L15: add si,[VARincr2] (* d := d + incr2 *)
- add di,[VARvertincr] (* vertical increment *)
-
- rol word ptr [BitShift],1
- jnc @L15a
-
- add bp,[VARVertincr]
- push [ReInitBit]
- pop [BitShift]
-
- @L15a: loop @L10
- jmp @LineDone
-
-
- (* routine for dy > dx (slope > 1) *)
- (* ES:DI -> video buffer *)
- (* AH = bit mask for 1st pixel *)
- (* AL = Bit Mask Register number *)
- (* CX = #pixels to draw *)
- (* DX = Graphics Controller port addr *)
- (* SI = decision variable *)
-
- (* Use BP for CharMapPtr and BH for CurrentWindowId *)
- @HiSlopeLine:
-
- @L21: cmp ds:[bp],bh
- jnz @L21a
- out dx,ax (* update Bit Mask Register *)
- or es:[di],al (* update bit planes *)
- @L21a:
- add di,[VARvertincr] (* increment y *)
- rol word ptr [BitShift],1
- jnc @L22
-
- add bp,[VARVertincr] (* Update char position vertically *)
- push [ReInitBit]
- pop [BitShift]
-
- @L22: or si,si (* test sign of d *)
- jns @L23 (* jump if d >= 0 *)
-
- add si,[VARincr1] (* d := d + incr1 *)
- loop @L21
- jmp @LineDone
-
-
- @L23: add si,[VARincr2] (* d := d + incr2 *)
-
- ror ah,1 (* rotate bit mask *)
- adc di,0 (* increment DI if when mask rotated to *)
- (* leftmost pixel position *)
- rol ah,1
- ror ah,1
- adc bp,0 (* Update char position horizontally *)
-
- loop @L21
-
- @LineDone:
- pop bp
- sti
- end;
-
-
-
- procedure Do_Set_EGAVGA;
- begin
- Do_INIT_X:=Do_INIT_EGAVGA;
- Do_DONE_X:=Do_DONE_EGAVGA;
- TVGraphCursorOn_X:=@TVGraphCursorOn_EGAVGA;
- TVGraphCursorOff_X:=@TVGraphCursorOff_EGAVGA;
- TVUpdateCursor_X:=@TVUpdateCursor_EGAVGA;
- Do_GraphMOV_X:=@Do_GraphMOV_EGAVGA;
- NewJmp_GraphMOV_X:=@NewJmp_GraphMOV_EGAVGA;
- Draw_Any_Line_X:=Draw_Any_Line_EGAVGA;
- Draw_Horiz_Line_X:=Draw_Horiz_Line_EGAVGA;
- Draw_Vert_Line_X:=Draw_Vert_Line_EGAVGA;
- end;
-
-